﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using Microsoft.Practices.Unity.InterceptionExtension;
using Microsoft.Practices.EnterpriseLibrary.Common.Configuration;
using System.Threading.Tasks;
using System.Windows;

namespace Infrastructure.WpfClient.Interceptors
{
    [ConfigurationElementType(typeof(CustomCallHandlerData))]
    public class AsyncInterceptor : ICallHandler
    {
        public AsyncInterceptor()
        { 
        }
        public IMethodReturn Invoke(IMethodInvocation input, GetNextHandlerDelegate getNext)
        {
            if (input.MethodBase is System.Reflection.MethodInfo)
            {
                var target = input.MethodBase as System.Reflection.MethodInfo;
                IMethodReturn result = null;
                if (target.ReturnType.FullName == typeof(void).FullName)
                {

                    var wait = new Views.WaitBox.WaitBoxWindow();
                    var dispatcher =  wait.Dispatcher;
                    Func<IMethodReturn> func = delegate() { return getNext()(input, getNext); };
                    AsyncCallback cb = new AsyncCallback(
                        delegate(IAsyncResult res){                            
                                result = func.EndInvoke(res);
                                var act = new Action(() => wait.Close());
                                dispatcher.Invoke(act);                            
                            }
                        );
                    func.BeginInvoke(cb, func);
                    wait.ShowDialog();
                    return result;
                }
                else
                {
                    return getNext()(input, getNext);
                }
            }
            return getNext()(input, getNext);
        }
        public void EndInvoke(IAsyncResult result)
        {
            Func<IMethodReturn> func = result.AsyncState as Func<IMethodReturn>;
            func.EndInvoke(result);
        }
        
        public int Order{get;set;}
    }
}
